package com.nanyang.tms.manager.ticket.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import com.nanyang.common.core.annotation.SystemLog;
import com.nanyang.common.core.dict.CommonEnum;
import com.nanyang.common.core.domain.ApiResult;
import com.nanyang.common.core.page.PageBean;
import com.nanyang.common.core.page.PageTableBean;
import com.nanyang.common.third.bos.entity.ObsRequestEntity;
import com.nanyang.common.third.bos.util.HwObsUtil;
import com.nanyang.common.tool.utils.convert.BeanUtils;
import com.nanyang.common.tool.utils.excel.AnalytExcel;
import com.nanyang.common.tool.utils.uuid.GlobalIdGeneratorUtil;
import com.nanyang.common.tool.utils.uuid.UUIDUtil;
import com.nanyang.sys.api.dto.request.obsauth.ObsAuthGetFilePathRequest;
import com.nanyang.sys.api.dto.response.obsauth.ObsAuthGetFilePathResponse;
import com.nanyang.sys.api.service.obsauth.ObsAuthRpcService;
import com.nanyang.tms.common.config.HwObsConfig;
import com.nanyang.tms.common.contstant.TmsSerializeConstant;
import com.nanyang.tms.common.dict.TmsCommonEnum;
import com.nanyang.tms.common.dict.TmsExceptionEnum;
import com.nanyang.tms.common.exception.TmsManagerException;
import com.nanyang.tms.common.util.RpcCheckUtils;
import com.nanyang.tms.common.util.TmsExceptionUtil;
import com.nanyang.tms.dao.ticket.TicketRecordDao;
import com.nanyang.tms.dao.ticket.TicketTypeDao;
import com.nanyang.tms.domain.ticket.*;
import com.nanyang.tms.manager.ticket.TicketManager;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.Reference;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.ss.usermodel.Sheet;
import org.redisson.api.RSemaphore;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

@Slf4j
@Component("ticketManager")
public class TicketManagerImpl implements TicketManager {
    @Autowired
    private TicketTypeDao ticketTypeDao;
    @Autowired
    private TicketRecordDao ticketRecordDao;
    @Autowired
    private GlobalIdGeneratorUtil globalIdGeneratorUtil;

    @Reference(version = "1.0.0", timeout = 10000, check = false)
    private ObsAuthRpcService obsAuthRpcService;
    @Autowired
    private HwObsConfig hwObsConfig;
    @Autowired
    private RedissonClient redissonClient;
    @Override
    public PageBean<TicketTypeVO> listTicket(TicketTypeQuery query) {
        try {
            if (query == null) {
                log.error(TmsCommonEnum.PARAM_IS_NULL.getCode() + TmsCommonEnum.PARAM_IS_NULL.getMessage());
                throw new TmsManagerException(TmsCommonEnum.PARAM_IS_NULL.getCode() ,TmsCommonEnum.PARAM_IS_NULL.getMessage());
            }
            Integer count = ticketTypeDao.countTicket(query);
            PageBean<TicketTypeVO> page = new PageTableBean<TicketTypeVO>(query.getPageIndex(), query.getPageSize());
            if (null != count && count != 0) {
                page.setTotalItem(count);
                int startRow = page.getStartRow();
                if (startRow > 0) {
                    startRow -= 1;
                }
                query.setStartRow(startRow);
                List<TicketTypeVO> ticketTypeVOS = ticketTypeDao.listTicket(query);
                List<String> collect = ticketTypeVOS.stream().map(TicketTypeVO::getTicketTypeCode).collect(Collectors.toList());
                List<TicketRecordVO> ticketRecordList = ticketRecordDao.queryRecordCount(collect);
                Map<String, Integer> collectMap = ticketRecordList.stream().collect(Collectors.toMap(TicketRecordVO::getTicketTypeCode,TicketRecordVO::getRecordCount));
                ticketTypeVOS.forEach(ticketTypeVO ->{
                    int recordCount=0;
                    if(CollectionUtil.isNotEmpty(collectMap)&&ObjectUtil.isNotNull(collectMap.get(ticketTypeVO.getTicketTypeCode()))){
                        recordCount=collectMap.get(ticketTypeVO.getTicketTypeCode());
                    }
                    ticketTypeVO.setCount(recordCount);
                });
                page.addAll(ticketTypeVOS);
            }
            return page;
        } catch (Exception e) {
            throw TmsExceptionUtil.wrapException(e);
        }
    }
    @Override
    public PageBean<TicketRecordVO> listTicketRecord(TicketRecordQuery query) {
        try {
            if (query == null) {
                log.error(TmsCommonEnum.PARAM_IS_NULL.getCode() + TmsCommonEnum.PARAM_IS_NULL.getMessage());
                throw new TmsManagerException(TmsCommonEnum.PARAM_IS_NULL.getCode() ,TmsCommonEnum.PARAM_IS_NULL.getMessage());
            }
            Integer count = ticketRecordDao.countTicketRecord(query);
            PageBean<TicketRecordVO> page = new PageTableBean<TicketRecordVO>(query.getPageIndex(), query.getPageSize());
            if (null != count && count != 0) {
                page.setTotalItem(count);
                int startRow = page.getStartRow();
                if (startRow > 0) {
                    startRow -= 1;
                }
                query.setStartRow(startRow);
                List<TicketRecordVO> ticketRecordVOS = ticketRecordDao.listTicketRecord(query);
                page.addAll(ticketRecordVOS);
            }
            return page;
        } catch (Exception e) {
            throw TmsExceptionUtil.wrapException(e);
        }
    }
    @SystemLog(module =SystemLog.Module.TICKET,template="ticketAdd")
    @Override
    public void saveTicketType(TicketTypeDO ticketTypeDO) {
        try {
            TicketTypeQuery ticketTypeQuery = new  TicketTypeQuery();
            ticketTypeQuery.setTicketTypeName(ticketTypeDO.getTicketTypeName());
            if (ticketTypeDao.queryVerifyTicketTypeName(ticketTypeQuery) > 0) {
                throw new TmsManagerException(TmsExceptionEnum.TICKET_IS_EXIST.getCode(),TmsExceptionEnum.TICKET_IS_EXIST.getMessage());
            }
            ticketTypeDO.setTicketTypeCode(TmsSerializeConstant.TICKET_KEY+globalIdGeneratorUtil.getNextSeq(TmsSerializeConstant.TICKET_SEQ_KEY, TmsSerializeConstant.SEQ_INCRBY));
            ticketTypeDao.insert(ticketTypeDO);
        } catch (TmsManagerException e) {
            throw TmsExceptionUtil.wrapException(e);
        }
    }
    @SystemLog(module =SystemLog.Module.TICKET,template="ticketUpdate")
    @Override
    public void updateTicketType(TicketTypeDO ticketTypeDO) {
        try {
            TicketTypeQuery ticketTypeQuery = new  TicketTypeQuery();
            ticketTypeQuery.setTicketTypeName(ticketTypeDO.getTicketTypeName());
            ticketTypeQuery.setTicketTypeCode(ticketTypeDO.getTicketTypeCode());
            if (ticketTypeDao.queryVerifyTicketTypeName(ticketTypeQuery) > 0) {
                throw new TmsManagerException(TmsExceptionEnum.TICKET_IS_EXIST.getCode(),TmsExceptionEnum.TICKET_IS_EXIST.getMessage());
            }
            ticketTypeDao.update(ticketTypeDO);
        } catch (TmsManagerException e) {
            throw TmsExceptionUtil.wrapException(e);
        }
    }
    @Override
    public void delTicketType(String ticketTypeCode) {
        try {
            TicketRecordQuery ticketRecordQuery = new TicketRecordQuery();
            ticketRecordQuery.setTicketTypeCode(ticketTypeCode);
            if (ticketRecordDao.countTicketRecord(ticketRecordQuery) > 0) {
                throw new TmsManagerException(TmsExceptionEnum.TICKET_RECORD_IS_EXIST.getCode(),TmsExceptionEnum.TICKET_RECORD_IS_EXIST.getMessage());
            }
            ticketTypeDao.deleteByCode(ticketTypeCode);
        } catch (TmsManagerException e) {
            throw TmsExceptionUtil.wrapException(e);
        }
    }


    private List<String> excelData(String path) {
        try {
            ObsAuthGetFilePathRequest request=new ObsAuthGetFilePathRequest();
            request.setSignUrl(path);
            ApiResult<ObsAuthGetFilePathResponse> filePathBySignUrl = obsAuthRpcService.getFilePathBySignUrl(request);
            if(RpcCheckUtils.isRpcInvokeError(filePathBySignUrl)){
                throw new TmsManagerException(TmsExceptionEnum.SIGN_URL_FAIL.getCode(),TmsExceptionEnum.SIGN_URL_FAIL.getMessage());
            }
            ObsRequestEntity entity = new ObsRequestEntity();
            BeanUtils.copyProperties(hwObsConfig, entity);
            String filePath = filePathBySignUrl.getData().getFilePath();
            File file = HwObsUtil.getResourceFile(entity,filePath , hwObsConfig.getLocalFilePath()+ UUIDUtil.uuid()+".xlsx");
            List<String> list=new ArrayList<>();
            Sheet sheet = AnalytExcel.getSheet(file, 0);
            int lastRowNum = sheet.getLastRowNum();
            for(int i=0;i<=lastRowNum;i++){
                Cell cell = sheet.getRow(i).getCell(0);
                cell.setCellType(CellType.STRING);
                list.add(cell.getStringCellValue());
            }
            return  list;
        } catch (IOException e) {
            log.error("获取上传文件异常：",path,e);
            throw new TmsManagerException(CommonEnum.SYSTEM_EXCEPTION.getCode(),CommonEnum.SYSTEM_EXCEPTION.getMessage()+e.getMessage());
        }
    }
    @SystemLog(module =SystemLog.Module.TICKET,template="ticketImport")
    @Override
    @Transactional
    public void importTicketNo(TicketImportVO ticketImportVO) {
        try {
            TicketTypeVO ticketTypeVO = ticketTypeDao.selectByCode(ticketImportVO.getTicketTypeCode());
            if(ObjectUtil.isNull(ticketTypeVO)){
                throw new TmsManagerException(CommonEnum.NO_CONTENT.getCode(),CommonEnum.NO_CONTENT.getMessage());
            }
            List<String> list=excelData(ticketImportVO.getTicketUrl());
            List<String> errorList=new ArrayList<>();
            if(CollectionUtil.isNotEmpty(list)){
                //规则校验
                list.forEach(str ->{
                    boolean matches = Pattern.matches(ticketTypeVO.getTicketRule(), str);
                    if(!matches){
                        errorList.add(str);
                    }
                    TicketRecordQuery ticketRecordQuery=new TicketRecordQuery();
                    ticketRecordQuery.setTicketNo(str);
                    int count = ticketRecordDao.countRepeatRecord(ticketRecordQuery);
                    if(count>0){
                        errorList.add(str);
                    }
                });
                if(CollectionUtil.isNotEmpty(errorList)){
                    throw new TmsManagerException(TmsExceptionEnum.TICKET_IS_ERROR.getCode(),String.format(TmsExceptionEnum.TICKET_IS_ERROR.getMessage(), StringUtils.join(errorList,",")));
                }
                //数据保存
                list.forEach(str ->{
                    TicketRecordDO ticketRecordDO=new TicketRecordDO();
                    ticketRecordDO.setTicketTypeCode(ticketTypeVO.getTicketTypeCode());
                    ticketRecordDO.setTicketNo(str);
                    ticketRecordDO.setGmtCreatePin(ticketImportVO.getGmtCreatePin());
                    ticketRecordDO.setIp(ticketImportVO.getIp());
                    ticketRecordDao.insert(ticketRecordDO);
                });
            }
            RSemaphore semaphore = redissonClient.getSemaphore(ticketImportVO.getTicketTypeCode());
            semaphore.releaseAsync(list.size());
        } catch (TmsManagerException e) {
            throw TmsExceptionUtil.wrapException(e);
        }
    }
}
